package com.loongtech.bi.manager.client;

import com.loongtech.bi.manager.system.BiPlatformManager;
import com.loongtech.bi.manager.system.GameParamConfigManager;
import com.loongtech.bi.support.CommonGameParam;
import com.loongtech.bi.support.chart.ChartData1;
import com.loongtech.bi.support.chart.ChartFlow;
import com.loongtech.bi.support.chart.ChartSelect;
import com.loongtech.core.jpa.manager.ManagerQueryCacheBase;
import com.loongtech.core.util.NumberUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 玩家分析-留存分析manager
 *
 * @author marin
 * @date 2015-09-15
 */
@Service
public class EventAnalysisToolManager extends ManagerQueryCacheBase<Object> {
    private static final long serialVersionUID = 1L;

    @Autowired
    private IterativeEventAnalysisManager iterativeEventAnalysisManager;


    public List<EventAnalysisDataChannel> getAllChannelData(Date dateStart, Date dateEnd, String queryPlatform, String queryChannel, String queryServer, Map<String, String> newUserEnterItemsRevise, Map<String, String> allEnterItemsRevise, int enterId) {
        Map<String, Map<String, EventAnalysisData>> tmpMap = new LinkedHashMap<>();

        List<Object[]> list = iterativeEventAnalysisManager.getIterativeEventAnalysisChannel(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        for (Object[] o : list) {
            EventAnalysisData data = new EventAnalysisData();
            String channelid = String.valueOf(o[0]);
            String stepcode = String.valueOf(o[1]);

            data.setStepcode(stepcode);
            data.setFinishnum(NumberUtil.parseInt(String.valueOf(o[2])));
            data.setUuidnum(NumberUtil.parseInt(String.valueOf(o[3])));

            Map<String, EventAnalysisData> tmp = tmpMap.get(channelid);
            if (tmp == null) {
                tmp = new LinkedHashMap<>();
                tmpMap.put(channelid, tmp);
            }
            tmp.put(stepcode, data);
        }

        //结果表
        List<EventAnalysisDataChannel> result = new ArrayList<>();
        for (Map.Entry<String, Map<String, EventAnalysisData>> entry : tmpMap.entrySet()) {
            String cid = entry.getKey();
            Map<String, EventAnalysisData> datas = entry.getValue();

            List<EventAnalysisData> dt = new ArrayList<>();

            //新用户进去入步骤
            if (enterId == CommonGameParam.EVENT_NEWUSER_STEPCODE.COMMONID) {
                addList(newUserEnterItemsRevise, dt, datas);
            }//全部用户进入步骤
            else if (enterId == CommonGameParam.EVENT_ALLUSER_STEPCODE.COMMONID) {
                addList(allEnterItemsRevise, dt, datas);
            }

            EventAnalysisDataChannel c = new EventAnalysisDataChannel();
            c.setChannelId(cid);
            c.setSteps(dt);

            if (dt != null && dt.size() > 0 && dt.get(0) != null) {
                c.setBeginnum(dt.get(0).getUuidnum());
                c.setEndnum(dt.get(dt.size() - 1).getUuidnum());
                c.setAllRadio(c.getBeginnum() == 0 ? 0 : c.getEndnum().doubleValue() / c.getBeginnum().doubleValue());
            } else {
                c.setBeginnum(0);
                c.setEndnum(0);
                c.setAllRadio(0.0);
            }

            result.add(c);
        }

        Collections.sort(result, new EventAnalysisDataChannel().comparatorBeginNum);
        return result;
    }

    public List<EventAnalysisDataByPhone> getAllDataByPhone(Date dateStart, Date dateEnd, String queryPlatform, String queryChannel, String queryServer, Map<String, String> newUserEnterItemsRevise) {
        //临时map
        Map<String, Map<String, EventAnalysisData>> tmpMap = new LinkedHashMap<>();
        List<Object[]> list = iterativeEventAnalysisManager.getIterativeEventAnalysisByPhone(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);
        //循环
        for (Object[] o : list) {
            String deviceModel = String.valueOf(o[0]);
            String stepcode = String.valueOf(o[1]);
            EventAnalysisData data = new EventAnalysisData();
            //步骤代码
            data.setStepcode(stepcode);
            data.setUuidnum(NumberUtil.parseInt(String.valueOf(o[2])));

            Map<String, EventAnalysisData> tmp = tmpMap.get(deviceModel);
            if (tmp == null) {
                tmp = new LinkedHashMap<>();
                tmpMap.put(deviceModel, tmp);
            }
            tmp.put(stepcode, data);
        }
        //结果表
        List<EventAnalysisDataByPhone> result = new ArrayList<>();
        for (Map.Entry<String, Map<String, EventAnalysisData>> entry : tmpMap.entrySet()) {
            String deveiceModel = entry.getKey();
            Map<String, EventAnalysisData> datas = entry.getValue();
            List<EventAnalysisData> dt = new ArrayList<>();
            //新用户进入步骤
            addListPhone(newUserEnterItemsRevise, dt, datas);
            EventAnalysisDataByPhone c = new EventAnalysisDataByPhone();
            c.setDevieModel(deveiceModel);
            c.setSteps(dt);
            if (dt.size() > 0) {
                for (EventAnalysisData aDt : dt) {
                    if (aDt != null) {
                        c.setBeginnum(aDt.getUuidnum());
                        break;
                    }
                }
            } else {
                c.setBeginnum(0);
            }
            result.add(c);
        }
        Collections.sort(result, new EventAnalysisDataByPhone().comparatorBeginNum);
        return result;
    }

    /**
     * 得到符合条件的所有数据
     *
     * @return
     */
    public List<EventAnalysisData> getAllData(Date dateStart, Date dateEnd, String queryPlatform, String queryChannel, String queryServer, Map<String, String> newUserEnterItemsRevise, Map<String, String> allEnterItemsRevise, int enterId) {
        //临时map
        Map<String, EventAnalysisData> tmpMap = new HashMap<>();

        List<Object[]> list = iterativeEventAnalysisManager.getIterativeEventAnalysis(dateStart, dateEnd, queryPlatform, queryChannel, queryServer);

        //循环
        for (Object[] o : list) {

            EventAnalysisData data = new EventAnalysisData();
            //步骤代码
            String stepcode = String.valueOf(o[0]);
            data.setStepcode(stepcode);
            data.setFinishnum(NumberUtil.parseInt(String.valueOf(o[1])));
            data.setUuidnum(NumberUtil.parseInt(String.valueOf(o[2])));

            tmpMap.put(stepcode, data);
        }

        //结果表
        List<EventAnalysisData> result = new ArrayList<>();

        //新用户进去入步骤
        if (enterId == CommonGameParam.EVENT_NEWUSER_STEPCODE.COMMONID) {
            addList(newUserEnterItemsRevise, result, tmpMap);
        }//全部用户进入步骤
        else if (enterId == CommonGameParam.EVENT_ALLUSER_STEPCODE.COMMONID) {
            addList(allEnterItemsRevise, result, tmpMap);
        }
        return result;
    }

    //根据新用户和全部用户显示
    private void addList(Map<String, String> map, List<EventAnalysisData> list, Map<String, EventAnalysisData> tmpMap) {
        int index = 0;
        Integer firstUuidnum = 0; //第一个uuid
        Integer beforeUuidnum = 0; //上一个uuid
        Integer currentUuidnum = 0; //当前的uuid

        for (Map.Entry<String, String> entry : map.entrySet()) {
            String stepcode = entry.getKey();
            //获得
            EventAnalysisData data = tmpMap.get(stepcode);

            if (data != null) {
                index++;
                data.setIndex(index);
                //第一步骤
                if (index == 1) {
                    firstUuidnum = data.getUuidnum();
                    data.setDistribute(1d);
                    data.setTotalAchieve(1d);
                    data.setLostRate(0d);
                } else {
                    currentUuidnum = data.getUuidnum();
                    //分布转化率
                    data.setDistribute(beforeUuidnum == 0 ? 0 : currentUuidnum.doubleValue() / beforeUuidnum.doubleValue());
                    data.setTotalAchieve(firstUuidnum == 0 ? 0 : currentUuidnum.doubleValue() / firstUuidnum.doubleValue());
                    //流失率
                    data.setLostRate((beforeUuidnum.doubleValue() - currentUuidnum.doubleValue()) == 0 ? 0 : (beforeUuidnum.doubleValue() - currentUuidnum.doubleValue()) / firstUuidnum.doubleValue());
                }
                beforeUuidnum = data.getUuidnum();
                //加入
                list.add(data);
            }
        }
    }

    //根据新用户和全部用户显示
    private void addListPhone(Map<String, String> map, List<EventAnalysisData> list, Map<String, EventAnalysisData> tmpMap) {
        int index = 0;
        Integer firstUuidnum = 0; //第一个uuid
        Integer beforeUuidnum = 0; //上一个uuid
        Integer currentUuidnum = 0; //当前的uuid

        for (Map.Entry<String, String> entry : map.entrySet()) {
            String stepcode = entry.getKey();
            EventAnalysisData data = tmpMap.get(stepcode);
            if (data != null) {
                index++;
                data.setIndex(index);
                //第一步骤
                if (index == 1) {
                    firstUuidnum = data.getUuidnum();
                    data.setDistribute(1d);
                    data.setTotalAchieve(1d);
                    data.setLostRate(0d);
                } else {
                    currentUuidnum = data.getUuidnum();
                    //分布转化率
                    data.setDistribute(beforeUuidnum == 0 ? 0 : currentUuidnum.doubleValue() / beforeUuidnum.doubleValue());
                    data.setTotalAchieve(firstUuidnum == 0 ? 0 : currentUuidnum.doubleValue() / firstUuidnum.doubleValue());
                    //流失率
                    data.setLostRate((beforeUuidnum.doubleValue() - currentUuidnum.doubleValue()) == 0 ? 0 : (beforeUuidnum.doubleValue() - currentUuidnum.doubleValue()) / firstUuidnum.doubleValue());
                }
                beforeUuidnum = data.getUuidnum();
                //加入
                list.add(data);
            } else {
                list.add(null);
            }
        }
    }

    public class EventAnalysisData {
        private Integer index; //序号
        private String stepcode; //步骤代码
        private String stepcodeName; //步骤名称
        private Integer finishnum; //完成数量
        private Integer uuidnum; //设备数量
        private Double distribute; //分步转化率
        private Double totalAchieve; //累计完成率
        private Double lostRate; //每步流失率

        public String getStepcode() {
            return stepcode;
        }

        public void setStepcode(String stepcode) {
            this.stepcode = stepcode;
            this.stepcodeName = (GameParamConfigManager.getItemsRevise(CommonGameParam.EVENT_ALLUSER_STEPCODE).get(stepcode) == null) ? stepcode : GameParamConfigManager.getItemsRevise(CommonGameParam.EVENT_ALLUSER_STEPCODE).get(stepcode);
        }

        public Integer getFinishnum() {
            return finishnum;
        }

        public void setFinishnum(Integer finishnum) {
            this.finishnum = finishnum;
        }

        public Integer getUuidnum() {
            return uuidnum;
        }

        public void setUuidnum(Integer uuidnum) {
            this.uuidnum = uuidnum;
        }

        public Double getDistribute() {
            return distribute;
        }

        public void setDistribute(Double distribute) {
            this.distribute = distribute;
        }

        public Double getTotalAchieve() {
            return totalAchieve;
        }

        public void setTotalAchieve(Double totalAchieve) {
            this.totalAchieve = totalAchieve;
        }

        public Integer getIndex() {
            return index;
        }

        public void setIndex(Integer index) {
            this.index = index;
        }

        public String getStepcodeName() {
            return stepcodeName;
        }

        public void setStepcodeName(String stepcodeName) {
            this.stepcodeName = stepcodeName;
        }

        public Double getLostRate() {
            return lostRate;
        }

        public void setLostRate(Double lostRate) {
            this.lostRate = lostRate;
        }
    }

    //折形图
    public class EventAnalysisData2 {
        private Integer index; //序号
        private String stepcode; //步骤代码
        @ChartFlow(name = "步骤代码")
        private String stepcodeName; //步骤代码
        private Integer finishnum; //完成数量
        private Integer uuidnum; //设备数量
        @ChartSelect(name = "设备数量", key = 1)
        @ChartData1(name = "分步转化率", key = 1)
        private Double distribute; //分步转化率
        @ChartData1(name = "累计完成率", key = 1)
        private Double totalAchieve; //累计完成率

        public String getStepcodeName() {
            return stepcodeName;
        }

        public void setStepcodeName(String stepcodeName) {
            this.stepcodeName = stepcodeName;
        }

        public String getStepcode() {
            return stepcode;
        }

        public void setStepcode(String stepcode) {
            this.stepcode = stepcode;
        }

        public Integer getFinishnum() {
            return finishnum;
        }

        public void setFinishnum(Integer finishnum) {
            this.finishnum = finishnum;
        }

        public Integer getUuidnum() {
            return uuidnum;
        }

        public void setUuidnum(Integer uuidnum) {
            this.uuidnum = uuidnum;
        }

        public Double getDistribute() {
            return distribute;
        }

        public void setDistribute(Double distribute) {
            this.distribute = distribute;
        }

        public Double getTotalAchieve() {
            return totalAchieve;
        }

        public void setTotalAchieve(Double totalAchieve) {
            this.totalAchieve = totalAchieve;
        }

        public Integer getIndex() {
            return index;
        }

        public void setIndex(Integer index) {
            this.index = index;
        }
    }

    //柱状图用
    public class EventAnalysisData1 {
        private Integer index; //序号

        private String stepcode; //步骤代码
        @ChartFlow(name = "步骤代码")
        private String stepcodeName; //步骤代码
        private Integer finishnum; //完成数量
        @ChartSelect(name = "设备数量", key = 1)
        @ChartData1(name = "设备数量", key = 1)
        private Integer uuidnum; //设备数量
        private Double distribute; //分步转化率
        private Double totalAchieve; //累计完成率

        public String getStepcodeName() {
            return stepcodeName;
        }

        public void setStepcodeName(String stepcodeName) {
            this.stepcodeName = stepcodeName;
        }

        public String getStepcode() {
            return stepcode;
        }

        public void setStepcode(String stepcode) {
            this.stepcode = stepcode;
        }

        public Integer getFinishnum() {
            return finishnum;
        }

        public void setFinishnum(Integer finishnum) {
            this.finishnum = finishnum;
        }

        public Integer getUuidnum() {
            return uuidnum;
        }

        public void setUuidnum(Integer uuidnum) {
            this.uuidnum = uuidnum;
        }

        public Double getDistribute() {
            return distribute;
        }

        public void setDistribute(Double distribute) {
            this.distribute = distribute;
        }

        public Double getTotalAchieve() {
            return totalAchieve;
        }

        public void setTotalAchieve(Double totalAchieve) {
            this.totalAchieve = totalAchieve;
        }

        public Integer getIndex() {
            return index;
        }

        public void setIndex(Integer index) {
            this.index = index;
        }
    }

    // 渠道数据
    public class EventAnalysisDataChannel {
        private List<EventAnalysisData> steps;  // 各步骤数据
        private Integer beginnum;  // 点击icon（激活设备）
        private Integer endnum;  // 进入游戏（新增设备）
        @ChartSelect(name = "整体通过率", key = 1)
        @ChartData1(name = "整体通过率", key = 1)
        private Double allRadio;  // 整体通过率（新增设备/激活设备）
        private String channelId;
        @ChartFlow(name = "渠道")
        private String channelName;

        public final Comparator<EventAnalysisDataChannel> comparatorRadio = new Comparator<EventAnalysisDataChannel>() {
            public int compare(EventAnalysisDataChannel s1, EventAnalysisDataChannel s2) {
                return s1.getAllRadio().compareTo(s2.getAllRadio());
            }
        };

        public final Comparator<EventAnalysisDataChannel> comparatorBeginNum = new Comparator<EventAnalysisDataChannel>() {
            @Override
            public int compare(EventAnalysisDataChannel s1, EventAnalysisDataChannel s2) {
                return s2.getBeginnum().compareTo(s1.getBeginnum());
            }
        };

        public List<EventAnalysisData> getSteps() {
            return steps;
        }

        public void setSteps(List<EventAnalysisData> steps) {
            this.steps = steps;
        }

        public Integer getBeginnum() {
            return beginnum;
        }

        public void setBeginnum(Integer beginnum) {
            this.beginnum = beginnum;
        }

        public Integer getEndnum() {
            return endnum;
        }

        public void setEndnum(Integer endnum) {
            this.endnum = endnum;
        }

        public Double getAllRadio() {
            return allRadio;
        }

        public void setAllRadio(Double allRadio) {
            this.allRadio = allRadio;
        }

        public String getChannelId() {
            return channelId;
        }

        public void setChannelId(String channelId) {
            this.channelId = channelId;
            this.channelName = BiPlatformManager.getChannelNameById(channelId);
        }

        public String getChannelName() {
            return channelName;
        }

        public void setChannelName(String channelName) {
            this.channelName = channelName;
        }
    }

    //分机型数据
    public class EventAnalysisDataByPhone {
        private List<EventAnalysisData> steps;  // 各步骤数据
        private String devieModel;
        private Integer beginnum;  // 激活设备


        public final Comparator<EventAnalysisDataByPhone> comparatorBeginNum = new Comparator<EventAnalysisDataByPhone>() {
            @Override
            public int compare(EventAnalysisDataByPhone s1, EventAnalysisDataByPhone s2) {
                return s2.getBeginnum().compareTo(s1.getBeginnum());
            }
        };

        public List<EventAnalysisData> getSteps() {
            return steps;
        }

        public void setSteps(List<EventAnalysisData> steps) {
            this.steps = steps;
        }

        public String getDevieModel() {
            return devieModel;
        }

        public void setDevieModel(String devieModel) {
            this.devieModel = devieModel;
        }

        public Integer getBeginnum() {
            return beginnum;
        }

        public void setBeginnum(Integer beginnum) {
            this.beginnum = beginnum;
        }
    }
}
